package com.bensoft.minesweeper.gui.minesweeperframe;

import com.bensoft.minesweeper.gui.GUILoader;
import com.bensoft.minesweeper.gui.minesweeperframe.displaypanel.Display3Digit;
import com.bensoft.minesweeper.gui.minesweeperframe.displaypanel.SmileyButton;
import com.bensoft.minesweeper.resources.FileResources;
import com.bensoft.minesweeper.resources.FileResources.ThemeChangeListener;
import java.awt.BorderLayout;
import java.awt.Color;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JPanel;
import javax.swing.border.BevelBorder;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;

/**
 * A panel that holds the time and the remaining bombs displays and the smiley
 * button. It also manages the game timer.
 *
 * @see Display3Digit
 * @see SmileyButton
 * @author Ben Wolsieffer
 */
public class DisplayPanel extends JPanel implements GUILoader {

    private Display3Digit remainingDisplay, timeDisplay;
    private Thread timerThread;
    private final Object timerLock = new Object();
    private volatile boolean timerStarted = false;
    private SmileyButton smileyButton;
    private JPanel smileyPanel;
    private CompoundBorder border;
    private static final EmptyBorder OUTER_PADDING_BORDER = new EmptyBorder(7, 7, 4, 7);
    private static final EmptyBorder INNER_PADDING_BORDER = new EmptyBorder(5, 6, 5, 6);

    public DisplayPanel() {
        init();
    }

    private void init() {
        initializeComponents();
        setLayouts();
        addComponents();
        addComponentListeners();
        otherInit();
    }

    @Override
    public void initializeComponents() {
        remainingDisplay = new Display3Digit();
        timeDisplay = new Display3Digit();
        smileyPanel = new JPanel();
        timerThread = new Thread(new Runnable() {
            private boolean wasStarted = false;

            @Override
            @SuppressWarnings("SleepWhileInLoop")
            public void run() {
                long lastTime = System.nanoTime();
                while (true) {
                    long currTime = System.nanoTime();
                    if (timerStarted) {
                        if (!wasStarted) {
                            lastTime = currTime;
                            wasStarted = true;
                        } else if (currTime - lastTime >= 1000000000) {
                            synchronized (timerLock) {
                                timeDisplay.setNumber(timeDisplay.getNumber() + 1);
                            }
                            FileResources.playTimerBop();
                            lastTime = currTime;
                        }
                    } else {
                        wasStarted = false;
                    }
                    try {
                        Thread.sleep(1);
                    } catch (InterruptedException ex) {
                    }
                }
            }
        });
        timerThread.start();
        smileyButton = new SmileyButton();
        //startTimer();
    }

    @Override
    public void setLayouts() {
        //setLayout(new BoxLayout(this, BoxLayout.LINE_AXIS));
        smileyPanel.setLayout(new BoxLayout(smileyPanel, BoxLayout.LINE_AXIS));
        setLayout(new BorderLayout());
    }

    @Override
    public void addComponents() {
        add(remainingDisplay, BorderLayout.LINE_START);
        //add(new JPanel(), BorderLayout.WEST);
        //add(Box.createHorizontalGlue());
        smileyPanel.add(Box.createHorizontalGlue());
        smileyPanel.add(smileyButton);
        smileyPanel.add(Box.createHorizontalGlue());
        //add(Box.createHorizontalGlue());
        add(smileyPanel, BorderLayout.CENTER);
        //add(new JPanel(), BorderLayout.EAST);
        add(timeDisplay, BorderLayout.LINE_END);
    }

    @Override
    public void addComponentListeners() {
    }

    @Override
    public void otherInit() {
        remainingDisplay.setAlignmentX(LEFT_ALIGNMENT);
        smileyButton.setAlignmentX(CENTER_ALIGNMENT);
        timeDisplay.setAlignmentX(RIGHT_ALIGNMENT);
//        revalidate();
        FileResources.addThemeChangeListener(new ThemeChangeListener() {
            @Override
            public void themeChanged() {
                border = new CompoundBorder(
                        new CompoundBorder(OUTER_PADDING_BORDER,
                        new BevelBorder(BevelBorder.LOWERED,
                        FileResources.getColor("displaypanel.border.outerhighlight"),
                        FileResources.getColor("displaypanel.border.innerhighlight"),
                        FileResources.getColor("displaypanel.border.outershadow"),
                        FileResources.getColor("displaypanel.border.innershadow"))),
                        INNER_PADDING_BORDER);
                setBorder(border);
                Color backgroundColor = FileResources.getColor("displaypanel.color");
                setBackground(backgroundColor);
                smileyPanel.setBackground(backgroundColor);
            }
        });
    }

    private void stopTimer() {
        timerStarted = false;
    }

    public void resetTimer() {
        stopTimer();
        synchronized (timerLock) {
            timeDisplay.setNumber(0);
        }
    }

    public void startTimer() {
        timerStarted = true;
    }

    public int getTime() {
        return timeDisplay.getNumber();
    }

    public void setRemainingMines(int n) {
        remainingDisplay.setNumber(n);
    }

    public int getRemainingMines() {
        return remainingDisplay.getNumber();
    }

    public void gameWon() {
        stopTimer();
        smileyButton.win();
    }

    public void gameLost() {
        stopTimer();
        smileyButton.kill();
    }

    /**
     * Sets the smiley button to the surprised face.
     */
    public void gridSpacePressed() {
        smileyButton.surprise();
    }

    /**
     * Sets the smiley button to the normal face.
     */
    public void gridSpaceReleased() {
        smileyButton.unSurprise();
    }
}